/*
 *  ExperimetalCompose2.cpp
 *  SoundController0002
 *
 *  Created by jiro on 10/11/23.
 *  Copyright 2010 jiro music. All rights reserved.
 *
 */


#include "ExperimetalCompose.h"
#include "../sc/SoundController.h"
#include <vector>
#include <iostream>

using namespace sc;
using namespace std;

vector< Note::MidiNumber > GetChordByMidiNumber( const Note::MidiNumber* numbers, int count ) 
{
	vector< Note::MidiNumber > chord( count );
	for ( int i = 0; i < count; i++ ) {
		chord[ i ] = numbers[ i ];
	}
	return chord;
}

void ExperimetalComposer::Compose03( const std::string& folderPath, unsigned int part )
{
	if ( part & 0x01 != 0x00 ) 
	{
		const SoundElement32* element;

		// melody 
		AudioRecorder32 recorder( 2, 1 );
		double time = 0.0;
		double length = 8;
		double powerOfX = 2.9;
		double adjuster = 0.2;
		double swell = 4.0;

		const WaveFunction& func = WaveFunctionFactory::CreateXSinX( powerOfX, 2 * length, false );
		const WaveTable& dynamicsTable = WaveTableFactory::Create( func, adjuster );

		const Note::MidiNumber notes0[] = { Note::C_2, Note::C_3, Note::D_3, Note::G_3, Note::B_3 };
		const Note::MidiNumber notes1[] = { Note::A_2, Note::A_3, Note::B_3, Note::FSharp_4 };
		const Note::MidiNumber notes0_swell[] = { Note::B_6, /*Note::D_6*/ };
		const Note::MidiNumber notes1_swell[] = { /*Note::B_6,*/ Note::FSharp_7 };

		vector< Note::MidiNumber > chord_0_0 = GetChordByMidiNumber( notes0, sizeof( notes0 ) / sizeof( Note::MidiNumber ) );
		vector< Note::MidiNumber > chord_1_0 = GetChordByMidiNumber( notes1, sizeof( notes1 ) / sizeof( Note::MidiNumber ) );
		vector< Note::MidiNumber > chord_0_1 = GetChordByMidiNumber( notes0_swell, sizeof( notes0_swell ) / sizeof( Note::MidiNumber ) );
		vector< Note::MidiNumber > chord_1_1 = GetChordByMidiNumber( notes1_swell, sizeof( notes1_swell ) / sizeof( Note::MidiNumber ) );

		vector< vector< Note::MidiNumber > > chords;
		chords.push_back( chord_0_0 );
		chords.push_back( chord_1_0 );
		chords.push_back( chord_0_0 );
		chords.push_back( chord_1_0 );
		chords.push_back( chord_0_0 );

		vector< vector< Note::MidiNumber > > chords_swell;
		chords_swell.push_back( vector< Note::MidiNumber >() );
		chords_swell.push_back( vector< Note::MidiNumber >() );
		chords_swell.push_back( chord_0_1 );
		chords_swell.push_back( chord_1_1 );
		chords_swell.push_back( chord_0_1 );

		for ( int i = 0; i < chords.size(); i++ )
		{
			const vector< Note::MidiNumber >& chord = chords[ i ];
			for ( int j = 0; j < chord.size(); j++ )
			{
				const Note::MidiNumber number = chord[ j ];
				const WaveTable& soundTable = WaveTableFactory::CreateSin( WellTemperament::GetFrequency( number ), 0.0, adjuster );
				element = SoundElementFactory32::Create( soundTable, dynamicsTable, length );
				recorder.Record( 0, 0, time, element, 0.5, 0.5 );
			}
			
			const vector< Note::MidiNumber >& chord_swell = chords_swell[ i ];
			for ( int j = 0; j < chord_swell.size(); j++ )
			{
				const Note::MidiNumber number = chord_swell[ j ];
				const double freq0 = WellTemperament::GetFrequency( number );
				const double freq1 = freq0 + swell;
				const WaveTable& soundTable0 = WaveTableFactory::CreateSin( freq0, 0.0, adjuster / 4.0 );
				const WaveTable& soundTable1 = WaveTableFactory::CreateSin( freq1, 0.5, adjuster / 4.0 );

				element = SoundElementFactory32::Create( soundTable0, dynamicsTable, length );
				recorder.Record( 0, 0, time, element, 0.5, 0.5 );

				element = SoundElementFactory32::Create( soundTable1, dynamicsTable, length );
				recorder.Record( 0, 0, time, element, 0.5, 0.5 );
				
			}
			time += length;
		}

	//	recorder.OutputAudioFile( folderPath + "sand box song.wav" );
		recorder.OutputAudioFile( folderPath + "sand_box_song.wav" );
	}

	if ( part & 0x10 != 0x00 ) 
	{
		const SoundElement32* element;

		// melody 
		AudioRecorder32 recorder( 2, 1 );
		double time = 0.0;
		double length = 8;
		double powerOfX = 2.9;
		double adjuster = 0.15;
		double swell = 4.0;

		const WaveFunction& func = WaveFunctionFactory::CreateXSinX( powerOfX, 2 * length, false );
		const WaveTable& dynamicsTable = WaveTableFactory::Create( func, adjuster );
				
		const double freqs0[] = { 
			WellTemperament::GetFrequency( Note::C_2 ),
			2 * freqs0[ 0 ], 
			9 * freqs0[ 1 ] / 8.0,
			3 * freqs0[ 1 ] / 2.0,
			15 * freqs0[ 1 ] / 8.0
		};
		const double freqs1[] = {
			WellTemperament::GetFrequency( Note::C_2 ),
			2 * freqs1[ 0 ],
			9 * freqs1[ 1 ] / 8.0,
			27 * freqs1[ 1 ] / 16.0, 
		};
		
		const double freqs0_swell[] = { 2 * freqs0[ 4 ] };
		const double freqs1_swell[] = { 2 * freqs1[ 3 ] };

		vector< double > chord_0_0( sizeof( freqs0 ) / sizeof( double ) );
		for ( int i = 0; i < chord_0_0.size(); i++ ) {
			chord_0_0[ i ] = freqs0[ i ];
		}

		vector< double > chord_1_0( sizeof( freqs1 ) / sizeof( double ) );
		for ( int i = 0; i < chord_1_0.size(); i++ ) {
			chord_1_0[ i ] = freqs0[ i ];
		}

		vector< double > chord_0_1( sizeof( freqs0_swell ) / sizeof( double ) );
		for ( int i = 0; i < chord_0_1.size(); i++ ) {
			chord_0_1[ i ] = freqs0_swell[ i ];
		}

		vector< double > chord_1_1( sizeof( freqs1_swell ) / sizeof( double ) );
		for ( int i = 0; i < chord_1_1.size(); i++ ) {
			chord_1_1[ i ] = freqs1_swell[ i ];
		}

		vector< vector< double > > chords;
		chords.push_back( chord_0_0 );
		chords.push_back( chord_1_0 );
		chords.push_back( chord_0_0 );
		chords.push_back( chord_1_0 );
		chords.push_back( chord_0_0 );

		vector< vector< double > > chords_swell;
		chords_swell.push_back( vector< double >() );
		chords_swell.push_back( vector< double >() );
		chords_swell.push_back( chord_0_1 );
		chords_swell.push_back( chord_1_1 );
		chords_swell.push_back( chord_0_1 );

		for ( int i = 0; i < chords.size(); i++ )
		{
			const vector< double >& chord = chords[ i ];
			for ( int j = 0; j < chord.size(); j++ )
			{
				const double freq = chord[ j ];
				const WaveTable& soundTable = WaveTableFactory::CreateSin( freq, 0.0, adjuster );
				element = SoundElementFactory32::Create( soundTable, dynamicsTable, length );
				recorder.Record( 0, 0, time, element, 0.5, 0.5 );
			}
			
			const vector< double >& chord_swell = chords_swell[ i ];
			for ( int j = 0; j < chord_swell.size(); j++ )
			{
				const double freq0 = chord_swell[ j ];
				const double freq1 = freq0 + swell;
				const WaveTable& soundTable0 = WaveTableFactory::CreateSin( freq0, 0.0, adjuster / 4.0 );
				const WaveTable& soundTable1 = WaveTableFactory::CreateSin( freq1, 0.5, adjuster / 4.0 );

				element = SoundElementFactory32::Create( soundTable0, dynamicsTable, length );
				recorder.Record( 0, 0, time, element, 0.5, 0.5 );

				element = SoundElementFactory32::Create( soundTable1, dynamicsTable, length );
				recorder.Record( 0, 0, time, element, 0.5, 0.5 );
				
			}
			time += length;
		}

//		recorder.OutputAudioFile( folderPath + "sand_box_song2.wav" );
	}


	if ( part & 0x0100 != 0x00 ) 
	{
		const SoundElement32* element;

		// melody 
		AudioRecorder32 recorder( 2, 1 );
		double time = 0.0;
		double length = 8;
		double powerOfX = 2.9;
		double adjuster = 0.2;
		double swell = 2;

		const WaveFunction& func = WaveFunctionFactory::CreateXSinX( powerOfX, 2 * length, false );
		const WaveTable& dynamicsTable = WaveTableFactory::Create( func, adjuster );

		const Note::MidiNumber notes0[] = { Note::C_2, Note::C_3, Note::D_3, Note::G_3, Note::E_4 };
		const Note::MidiNumber notes1[] = { Note::D_2, Note::D_3, Note::E_3, Note::B_3, Note::FSharp_4 };
		const Note::MidiNumber notes0_swell[] = { Note::E_6, /*Note::D_6*/ };
		const Note::MidiNumber notes1_swell[] = { /*Note::B_6,*/ Note::FSharp_5 };

		vector< Note::MidiNumber > chord_0_0 = GetChordByMidiNumber( notes0, sizeof( notes0 ) / sizeof( Note::MidiNumber ) );
		vector< Note::MidiNumber > chord_1_0 = GetChordByMidiNumber( notes1, sizeof( notes1 ) / sizeof( Note::MidiNumber ) );
		vector< Note::MidiNumber > chord_0_1 = GetChordByMidiNumber( notes0_swell, sizeof( notes0_swell ) / sizeof( Note::MidiNumber ) );
		vector< Note::MidiNumber > chord_1_1 = GetChordByMidiNumber( notes1_swell, sizeof( notes1_swell ) / sizeof( Note::MidiNumber ) );

		vector< vector< Note::MidiNumber > > chords;
		chords.push_back( chord_0_0 );
		chords.push_back( chord_1_0 );
		chords.push_back( chord_0_0 );
		chords.push_back( chord_1_0 );
		chords.push_back( chord_0_0 );

		vector< vector< Note::MidiNumber > > chords_swell;
		chords_swell.push_back( vector< Note::MidiNumber >() );
		chords_swell.push_back( vector< Note::MidiNumber >() );
		chords_swell.push_back( chord_0_1 );
		chords_swell.push_back( chord_1_1 );
		chords_swell.push_back( chord_0_1 );

		for ( int i = 0; i < chords.size(); i++ )
		{
			const vector< Note::MidiNumber >& chord = chords[ i ];
			for ( int j = 0; j < chord.size(); j++ )
			{
				const Note::MidiNumber number = chord[ j ];
				const WaveTable& soundTable = WaveTableFactory::CreateSin( WellTemperament::GetFrequency( number ), 0.0, adjuster );
				element = SoundElementFactory32::Create( soundTable, dynamicsTable, length );
				recorder.Record( 0, 0, time, element, 0.5, 0.5 );
			}
			
			const vector< Note::MidiNumber >& chord_swell = chords_swell[ i ];
			for ( int j = 0; j < chord_swell.size(); j++ )
			{
				const Note::MidiNumber number = chord_swell[ j ];
				const double freq0 = WellTemperament::GetFrequency( number );
				const double freq1 = freq0 + swell;
				const WaveTable& soundTable0 = WaveTableFactory::CreateSin( freq0, 0.0, adjuster / 4.0 );
				const WaveTable& soundTable1 = WaveTableFactory::CreateSin( freq1, 0.5, adjuster / 4.0 );

				element = SoundElementFactory32::Create( soundTable0, dynamicsTable, length );
				recorder.Record( 0, 0, time, element, 0.5, 0.5 );

				element = SoundElementFactory32::Create( soundTable1, dynamicsTable, length );
				recorder.Record( 0, 0, time, element, 0.5, 0.5 );
				
			}
			time += length;
		}
		recorder.OutputAudioFile( folderPath + "sand_box_song3.wav" );
	}

	if ( part & 0x1000 != 0x00 ) 
	{
		const SoundElement32* element;

		// melody 
		AudioRecorder32 recorder( 2, 1 );
		double time = 0.0;
		double length = 8;
		double powerOfX = 2.9;
		double adjuster = 0.2;
		double swell = 2;

		const WaveFunction& func = WaveFunctionFactory::CreateXSinX( powerOfX, 2 * length, false );
		const WaveTable& dynamicsTable = WaveTableFactory::Create( func, adjuster );

		const Note::MidiNumber notes0[] = { Note::C_2, Note::G_2, Note::D_3, Note::A_3 };
		const Note::MidiNumber notes1[] = { Note::D_2, Note::A_2, Note::E_3, Note::B_3 };
		const Note::MidiNumber notes0_swell[] = { Note::A_5, /*Note::D_6*/ };
		const Note::MidiNumber notes1_swell[] = { /*Note::B_6,*/ Note::B_5 };

		vector< Note::MidiNumber > chord_0_0 = GetChordByMidiNumber( notes0, sizeof( notes0 ) / sizeof( Note::MidiNumber ) );
		vector< Note::MidiNumber > chord_1_0 = GetChordByMidiNumber( notes1, sizeof( notes1 ) / sizeof( Note::MidiNumber ) );
		vector< Note::MidiNumber > chord_0_1 = GetChordByMidiNumber( notes0_swell, sizeof( notes0_swell ) / sizeof( Note::MidiNumber ) );
		vector< Note::MidiNumber > chord_1_1 = GetChordByMidiNumber( notes1_swell, sizeof( notes1_swell ) / sizeof( Note::MidiNumber ) );

		vector< vector< Note::MidiNumber > > chords;
		chords.push_back( chord_0_0 );
		chords.push_back( chord_1_0 );
		chords.push_back( chord_0_0 );
		chords.push_back( chord_1_0 );
		chords.push_back( chord_0_0 );

		vector< vector< Note::MidiNumber > > chords_swell;
		chords_swell.push_back( vector< Note::MidiNumber >() );
		chords_swell.push_back( vector< Note::MidiNumber >() );
		chords_swell.push_back( chord_0_1 );
		chords_swell.push_back( chord_1_1 );
		chords_swell.push_back( chord_0_1 );

		for ( int i = 0; i < chords.size(); i++ )
		{
			const vector< Note::MidiNumber >& chord = chords[ i ];
			for ( int j = 0; j < chord.size(); j++ )
			{
				const Note::MidiNumber number = chord[ j ];
				const WaveTable& soundTable = WaveTableFactory::CreateSin( WellTemperament::GetFrequency( number ), 0.0, adjuster );
				element = SoundElementFactory32::Create( soundTable, dynamicsTable, length );
				recorder.Record( 0, 0, time, element, 0.5, 0.5 );
			}
			
			const vector< Note::MidiNumber >& chord_swell = chords_swell[ i ];
			for ( int j = 0; j < chord_swell.size(); j++ )
			{
				const Note::MidiNumber number = chord_swell[ j ];
				const double freq0 = WellTemperament::GetFrequency( number );
				const double freq1 = freq0 + swell;
				const WaveTable& soundTable0 = WaveTableFactory::CreateSin( freq0, 0.0, adjuster / 4.0 );
				const WaveTable& soundTable1 = WaveTableFactory::CreateSin( freq1, 0.5, adjuster / 4.0 );

				element = SoundElementFactory32::Create( soundTable0, dynamicsTable, length );
				recorder.Record( 0, 0, time, element, 0.5, 0.5 );

				element = SoundElementFactory32::Create( soundTable1, dynamicsTable, length );
				recorder.Record( 0, 0, time, element, 0.5, 0.5 );
				
			}
			time += length;
		}
		recorder.OutputAudioFile( folderPath + "sand_box_song4.wav" );
	}

	if ( ( part & 0x010000 ) != 0x00 ) 
	{
		const SoundElement32* element;

		// melody 
		AudioRecorder32 recorder( 2, 1 );
		double time = 0.0;
		double length = 8;
		double powerOfX = 2.9;
		double adjuster = 0.2;
//		double swell = 2;

		const WaveFunction& func = WaveFunctionFactory::CreateXSinX( 1, 2 * length, false );
//		const WaveFunction& func = WaveFunctionFactory::CreateXSinX( powerOfX, 2 * length, false );
		const WaveTable& dynamicsTable = WaveTableFactory::Create( func, adjuster );

		const Note::MidiNumber notes0[] = { Note::E_2, Note::E_3, Note::C_4, Note::D_4, Note::G_3 };
		const Note::MidiNumber notes1[] = { Note::D_2, Note::D_3, Note::E_3, Note::B_3, Note::FSharp_4 };
		const Note::MidiNumber notes2[] = { Note::C_3, Note::G_3, Note::D_4 };
		const Note::MidiNumber notes3[] = { Note::A_2, Note::E_3, Note::B_3 };
		const Note::MidiNumber notes4[] = { Note::G_2, Note::D_3, Note::A_3 };
		const Note::MidiNumber notes5[] = { Note::E_2, Note::A_3, Note::B_3, Note::FSharp_4 };
		const Note::MidiNumber notes6[] = { Note::C_2, Note::G_2, Note::D_3, Note::A_3 };

		vector< Note::MidiNumber > chord_0_0 = GetChordByMidiNumber( notes0, sizeof( notes0 ) / sizeof( Note::MidiNumber ) );
		vector< Note::MidiNumber > chord_1_0 = GetChordByMidiNumber( notes1, sizeof( notes1 ) / sizeof( Note::MidiNumber ) );
		vector< Note::MidiNumber > chord_2_0 = GetChordByMidiNumber( notes2, sizeof( notes2 ) / sizeof( Note::MidiNumber ) );
		vector< Note::MidiNumber > chord_3_0 = GetChordByMidiNumber( notes3, sizeof( notes3 ) / sizeof( Note::MidiNumber ) );
		vector< Note::MidiNumber > chord_4_0 = GetChordByMidiNumber( notes4, sizeof( notes4 ) / sizeof( Note::MidiNumber ) );
		vector< Note::MidiNumber > chord_5_0 = GetChordByMidiNumber( notes5, sizeof( notes5 ) / sizeof( Note::MidiNumber ) );
		vector< Note::MidiNumber > chord_6_0 = GetChordByMidiNumber( notes6, sizeof( notes6 ) / sizeof( Note::MidiNumber ) );
		
		vector< vector< Note::MidiNumber > > chords;
		chords.push_back( chord_0_0 );
		chords.push_back( chord_1_0 );
		chords.push_back( chord_2_0 );
		chords.push_back( chord_3_0 );
		chords.push_back( chord_4_0 );
		chords.push_back( chord_5_0 );
		chords.push_back( chord_6_0 );

		for ( int i = 0; i < chords.size(); i++ )
		{
			//	record chord
			const vector< Note::MidiNumber >& chord = chords[ i ];
			for ( int j = 0; j < chord.size(); j++ )
			{
				const Note::MidiNumber number = chord[ j ];
				const WaveTable& soundTable = WaveTableFactory::CreateSin( WellTemperament::GetFrequency( number ), 0.0, adjuster );
				element = SoundElementFactory32::Create( soundTable, dynamicsTable, length );
				recorder.Record( 0, 0, time, element, 0.5, 0.5 );
			}
			
			//	rechord swell
			{
				const double freq0 = 2 * WellTemperament::GetFrequency( chord.back() );
				const double freq1 = freq0 + 4;
				
				const WaveTable& soundTable0 = WaveTableFactory::CreateSin( freq0, 0.0, adjuster / 2 );
				element = SoundElementFactory32::Create( soundTable0, dynamicsTable, length );
				recorder.Record( 0, 0, time, element, 0.5, 0.5 );

				const WaveTable& soundTable1 = WaveTableFactory::CreateSin( freq1, 0.5, adjuster / 2 );
				element = SoundElementFactory32::Create( soundTable1, dynamicsTable, length );
				recorder.Record( 0, 0, time, element, 0.5, 0.5 );
				
			}

			{
				const WaveFunction& func = WaveFunctionFactory::CreateXSinX( powerOfX, 2 * length, false );
				const WaveTable& dynamicsTable = WaveTableFactory::Create( func, adjuster / 18 );

				const double freq0 = 4 * WellTemperament::GetFrequency( chord.back() );
				const double freq1 = freq0 + 0.25;

				const WaveTable& soundTable0 = WaveTableFactory::CreateSin( freq0, 0.0, adjuster );
				element = SoundElementFactory32::Create( soundTable0, dynamicsTable, length / ( 2 + 2 * ( i % 2 ) ) );
				recorder.Record( 0, 0, time, element, 0.25, 0.25 );

				const WaveTable& soundTable1 = WaveTableFactory::CreateSin( freq1, 0.5, adjuster );
				element = SoundElementFactory32::Create( soundTable1, dynamicsTable, length / ( 2 + 2 * ( i % 2 ) ) );
				recorder.Record( 0, 0, time, element, 0.25, 0.25 );
				
			}

			time += length;
		}
		recorder.OutputAudioFile( folderPath + "sand_box_song5.wav" );
	}

	if ( ( part & 0x100000 ) != 0x00 ) 
	{
		const SoundElement32* element;

		// melody 
		AudioRecorder32 recorder( 2, 1 );
		double time = 0.0;
		double length = 4;
		double powerOfX = 3;
		double adjuster = 0.2;
//		double swell = 2;

//		const WaveFunction& func = WaveFunctionFactory::CreateXSinX( 1, 2 * length, false );
		const WaveFunction& func = WaveFunctionFactory::CreateXSinX( powerOfX, 2 * length, false );
		const WaveTable& dynamicsTable = WaveTableFactory::Create( func, adjuster );

		const Note::MidiNumber notes0[] = { Note::DFlat_2, Note::DFlat_3, Note::F_4, Note::BFlat_4, Note::C_5 };
		const Note::MidiNumber notes1[] = { Note::EFlat_2, Note::EFlat_3, Note::GFlat_4, Note::DFlat_5 };
		const Note::MidiNumber notes2[] = { Note::EFlat_2, Note::EFlat_3, Note::BFlat_4, Note::DFlat_5 };
		const Note::MidiNumber notes3[] = { Note::E_2, Note::E_3, Note::FSharp_4, Note::B_4, Note::DSharp_5 };

		vector< Note::MidiNumber > chord_0_0 = GetChordByMidiNumber( notes0, sizeof( notes0 ) / sizeof( Note::MidiNumber ) );
		vector< Note::MidiNumber > chord_1_0 = GetChordByMidiNumber( notes1, sizeof( notes1 ) / sizeof( Note::MidiNumber ) );
		vector< Note::MidiNumber > chord_2_0 = GetChordByMidiNumber( notes2, sizeof( notes2 ) / sizeof( Note::MidiNumber ) );
		vector< Note::MidiNumber > chord_3_0 = GetChordByMidiNumber( notes3, sizeof( notes3 ) / sizeof( Note::MidiNumber ) );
		
		vector< vector< Note::MidiNumber > > chords;
		chords.push_back( chord_0_0 );
		chords.push_back( chord_1_0 );
		chords.push_back( chord_2_0 );
		chords.push_back( chord_3_0 );
		chords.push_back( chord_2_0 );
		chords.push_back( chord_1_0 );
		chords.push_back( chord_0_0 );

		for ( int i = 0; i < chords.size(); i++ )
		{
			//	record chord
			const vector< Note::MidiNumber >& chord = chords[ i ];
			for ( int j = 0; j < chord.size(); j++ )
			{
				const Note::MidiNumber number = chord[ j ];
				const WaveTable& soundTable = WaveTableFactory::CreateSin( WellTemperament::GetFrequency( number ), 0.0, adjuster );
				element = SoundElementFactory32::Create( soundTable, dynamicsTable, length );
				recorder.Record( 0, 0, time, element, 0.25, 0.25 );
			}
/*
			//	rechord swell
			{
				const double freq0 = 2 * WellTemperament::GetFrequency( chord.back() );
				const double freq1 = freq0 + 4;
				
				const WaveTable& soundTable0 = WaveTableFactory::CreateSin( freq0, 0.0, adjuster / 2 );
				element = SoundElementFactory32::Create( soundTable0, dynamicsTable, length );
				recorder.Record( 0, 0, time, element, 0.25, 0.25 );

				const WaveTable& soundTable1 = WaveTableFactory::CreateSin( freq1, 0.5, adjuster / 2 );
				element = SoundElementFactory32::Create( soundTable1, dynamicsTable, length );
				recorder.Record( 0, 0, time, element, 0.25, 0.25 );
				
			}
*/
			{
				const WaveFunction& func = WaveFunctionFactory::CreateXSinX( powerOfX, 2 * length, false );
				const WaveTable& dynamicsTable = WaveTableFactory::Create( func, adjuster / 18 );

				const double freq0 = 4 * WellTemperament::GetFrequency( chord.back() );
				const double freq1 = freq0 + 0.5;

				const WaveTable& soundTable0 = WaveTableFactory::CreateSin( freq0, 0.0, adjuster );
				element = SoundElementFactory32::Create( soundTable0, dynamicsTable, length );
//				element = SoundElementFactory32::Create( soundTable0, dynamicsTable, length / ( 2 + 2 * ( i % 2 ) ) );
				recorder.Record( 0, 0, time, element, 0.25, 0.25 );

				const WaveTable& soundTable1 = WaveTableFactory::CreateSin( freq1, 0.5, adjuster );
				element = SoundElementFactory32::Create( soundTable1, dynamicsTable, length );
//				element = SoundElementFactory32::Create( soundTable1, dynamicsTable, length / ( 2 + 2 * ( i % 2 ) ) );
				recorder.Record( 0, 0, time, element, 0.25, 0.25 );
			}
			time += length;
		}
		recorder.OutputAudioFile( folderPath + "sand_box_song6.wav" );
	}

	if ( ( part & 0x1000000 ) != 0x00 ) 
	{
		const SoundElement32* element;

		AudioRecorder32 recorder( 2, 1 );
		double time = 0.0;
		double length = 8;
		double powerOfX = 2.9;
		double adjuster = 0.2;
//		double swell = 2;

		const WaveFunction& func = WaveFunctionFactory::CreateXSinX( 1, 2 * length, false );
//		const WaveFunction& func = WaveFunctionFactory::CreateXSinX( powerOfX, 2 * length, false );
		const WaveTable& dynamicsTable = WaveTableFactory::Create( func, adjuster );

		const Note::MidiNumber notes0[] = { Note::C_2, Note::C_3, Note::D_3, Note::G_3, Note::E_4 };
		const Note::MidiNumber notes1[] = { Note::D_2, Note::D_3, Note::B_3, Note::E_4, Note::FSharp_4 };
		const Note::MidiNumber notes2[] = { Note::FSharp_2, Note::FSharp_3, Note::CSharp_4, Note::GSharp_4 };
		const Note::MidiNumber notes3[] = { Note::B_1, Note::B_2, Note::FSharp_4, Note::A_3, Note::E_4  };

		vector< Note::MidiNumber > chord_0_0 = GetChordByMidiNumber( notes0, sizeof( notes0 ) / sizeof( Note::MidiNumber ) );
		vector< Note::MidiNumber > chord_1_0 = GetChordByMidiNumber( notes1, sizeof( notes1 ) / sizeof( Note::MidiNumber ) );
		vector< Note::MidiNumber > chord_2_0 = GetChordByMidiNumber( notes2, sizeof( notes2 ) / sizeof( Note::MidiNumber ) );
		vector< Note::MidiNumber > chord_3_0 = GetChordByMidiNumber( notes3, sizeof( notes3 ) / sizeof( Note::MidiNumber ) );
		
		vector< vector< Note::MidiNumber > > chords;
		chords.push_back( chord_0_0 );
		chords.push_back( chord_1_0 );
		chords.push_back( chord_2_0 );
		chords.push_back( chord_3_0 );

		for ( int i = 0; i < chords.size(); i++ )
		{
			//	record chord
			const vector< Note::MidiNumber >& chord = chords[ i ];
			for ( int j = 0; j < chord.size(); j++ )
			{
				const Note::MidiNumber number = chord[ j ];
				const WaveTable& soundTable = WaveTableFactory::CreateSin( WellTemperament::GetFrequency( number ), 0.0, adjuster );
				element = SoundElementFactory32::Create( soundTable, dynamicsTable, length );
				recorder.Record( 0, 0, time, element, 0.5, 0.5 );
			}
			
			//	record swell
			{
				const double freq0 = 2 * WellTemperament::GetFrequency( chord.back() );
				const double freq1 = freq0 + 4;
				
				const WaveTable& soundTable0 = WaveTableFactory::CreateSin( freq0, 0.0, adjuster / 2 );
				element = SoundElementFactory32::Create( soundTable0, dynamicsTable, length );
				recorder.Record( 0, 0, time, element, 0.5, 0.5 );

				const WaveTable& soundTable1 = WaveTableFactory::CreateSin( freq1, 0.5, adjuster / 2 );
				element = SoundElementFactory32::Create( soundTable1, dynamicsTable, length );
				recorder.Record( 0, 0, time, element, 0.5, 0.5 );
				
			}

			{
				const WaveFunction& func = WaveFunctionFactory::CreateXSinX( powerOfX, 2 * length, false );
				const WaveTable& dynamicsTable = WaveTableFactory::Create( func, adjuster / 18 );

				const double freq0 = 4 * WellTemperament::GetFrequency( chord.back() );
				const double freq1 = freq0 + 0.25;

				const WaveTable& soundTable0 = WaveTableFactory::CreateSin( freq0, 0.0, adjuster );
				element = SoundElementFactory32::Create( soundTable0, dynamicsTable, length / ( 2 + 2 * ( i % 2 ) ) );
				recorder.Record( 0, 0, time, element, 0.25, 0.25 );

				const WaveTable& soundTable1 = WaveTableFactory::CreateSin( freq1, 0.5, adjuster );
				element = SoundElementFactory32::Create( soundTable1, dynamicsTable, length / ( 2 + 2 * ( i % 2 ) ) );
				recorder.Record( 0, 0, time, element, 0.25, 0.25 );
				
			}

			time += length;
		}
		recorder.OutputAudioFile( folderPath + "sand_box_song7.wav" );
	}
	
	if ( ( part & 0x01000000 ) != 0x00 ) 
	{
		// melody 
		AudioRecorder32 recorder_melody( 2, 1 );
		AudioRecorder32 recorder_chord( 2, 1 );
		double time = 0.0;
		double length = 0.2;
		double powerOfX = 2.0;
		double adjuster = 1.0;

//		const WaveFunction& func = WaveFunctionFactory::CreateXSinX( powerOfX, 2 * length, true );
		const WaveFunction& func = WaveFunctionFactory::CreateXSinX( powerOfX, 2 * length, false );
		const WaveTable& dynamicsTable = WaveTableFactory::Create( func, adjuster );

		const Note::MidiNumber notes0[] = { 
			Note::E_3, Note::C_4, Note::D_4, Note::G_4, Note::D_5, Note::E_5,
			Note::FSharp_5, Note::B_4, Note::E_4, Note::D_4 };

		time = 0.0;
		for ( int i = 0; i < sizeof( notes0 ) / sizeof( Note::MidiNumber ); i++ )
		{
			Note::MidiNumber number = notes0[ i ];
			const WaveTable& soundTable = WaveTableFactory::CreateSin( WellTemperament::GetFrequency( number ), 0.0, adjuster );
			const SoundElement32* element = SoundElementFactory32::Create( soundTable, dynamicsTable, length );
			recorder_melody.Record( 0, 0, time, element, 0.5, 0.5 );
			time += length;
		}
		recorder_melody.OutputAudioFile( folderPath + "sand_box_song8_melody.wav" );
		
		const Note::MidiNumber chord0[] = {
			Note::E_2, Note::C_3, Note::D_4, Note::G_4, Note::D_5, Note::E_5,
		};
		const Note::MidiNumber chord1[] = {
			Note::D_2, Note::E_4, Note::B_4, Note::FSharp_4,
		};
		int count0 = sizeof( chord0 ) / sizeof( Note::MidiNumber );
		int count1 = sizeof( chord1 ) / sizeof( Note::MidiNumber );

		double length0 = length * count0;
		double length1 = length * count1;
		const WaveFunction& chordDynamicsFunc0 = WaveFunctionFactory::CreateXSinX( 1, 2 * length0, false );
		const WaveFunction& chordDynamicsFunc1 = WaveFunctionFactory::CreateXSinX( 1, 2 * length1, false );
		const WaveTable& chordDynamicsTable0 = WaveTableFactory::Create( chordDynamicsFunc0, adjuster );
		const WaveTable& chordDynamicsTable1 = WaveTableFactory::Create( chordDynamicsFunc1, adjuster );
		time = 0.0;
		for ( int i = 0; i < count0; i++ ) {
			Note::MidiNumber number = chord0[ i ];
			const WaveTable& soundTable = WaveTableFactory::CreateSin( WellTemperament::GetFrequency( number ), 0.0, adjuster );
			const SoundElement32* element = SoundElementFactory32::Create( soundTable, chordDynamicsTable0, length0 );
			recorder_chord.Record( 0, 0, time, element, 1.0 / count0, 1.0 / count0 );
		}
		time += length0;
		for ( int i = 0; i < count1; i++ ) {
			Note::MidiNumber number = chord1[ i ];
			const WaveTable& soundTable = WaveTableFactory::CreateSin( WellTemperament::GetFrequency( number ), 0.0, adjuster );
			const SoundElement32* element = SoundElementFactory32::Create( soundTable, chordDynamicsTable1, length1 );
			recorder_chord.Record( 0, 0, time, element, 1.0 / count1, 1.0 / count1 );
		}
		recorder_chord.OutputAudioFile( folderPath + "sand_box_song8_chord.wav" );
	}

	if ( ( part & 0x10000000 ) != 0x00 ) 
	{
		const SoundElement32* element;

		AudioRecorder32 recorder( 2, 1 );
		double time = 0.0;
		double length = 4;
		double powerOfX = 2.9;
		double adjuster = 0.2;
//		double swell = 2;

		const WaveFunction& func = WaveFunctionFactory::CreateXSinX( powerOfX, 2 * length, true );
//		const WaveFunction& func = WaveFunctionFactory::CreateXSinX( powerOfX, 2 * length, false );
		const WaveTable& dynamicsTable = WaveTableFactory::Create( func, adjuster );

		const Note::MidiNumber notes0[] = { Note::D_2, Note::D_3, Note::BFlat_3, Note::C_4, Note::F_4 };
		const Note::MidiNumber notes1[] = { Note::AFlat_2, Note::AFlat_3, Note::EFlat_4, Note::BFlat_4 };
		const Note::MidiNumber notes2[] = { Note::D_2, Note::D_3, Note::A_3, Note::E_4, Note::B_4 };

		vector< Note::MidiNumber > chord_0_0 = GetChordByMidiNumber( notes0, sizeof( notes0 ) / sizeof( Note::MidiNumber ) );
		vector< Note::MidiNumber > chord_1_0 = GetChordByMidiNumber( notes1, sizeof( notes1 ) / sizeof( Note::MidiNumber ) );
		vector< Note::MidiNumber > chord_2_0 = GetChordByMidiNumber( notes2, sizeof( notes2 ) / sizeof( Note::MidiNumber ) );
		
		vector< vector< Note::MidiNumber > > chords;
		chords.push_back( chord_0_0 );
		chords.push_back( chord_1_0 );
		chords.push_back( chord_2_0 );

		for ( int i = 0; i < chords.size(); i++ )
		{
			//	record chord
			const vector< Note::MidiNumber >& chord = chords[ i ];
			for ( int j = 0; j < chord.size(); j++ )
			{
				const Note::MidiNumber number = chord[ j ];
				const WaveTable& soundTable = WaveTableFactory::CreateSin( WellTemperament::GetFrequency( number ), 0.0, adjuster );
				element = SoundElementFactory32::Create( soundTable, dynamicsTable, length );
				recorder.Record( 0, 0, time, element, 0.5, 0.5 );
			}
			time += length;
		}
		recorder.OutputAudioFile( folderPath + "sand_box_song9.wav" );
	}

}

void ExperimetalComposer::Compose04( const std::string& folderPath, unsigned int part )
{
	if ( 0 == part ) {

		double length = 5.0;
		double powerOfX = 1.0;
		double adjuster = 1.0;
		const WaveFunction& func = WaveFunctionFactory::CreateXSinX( powerOfX, 2 * length, true );
		const WaveTable& dynamicsTable = WaveTableFactory::Create( func, adjuster );
	
		double freqA = WellTemperament::GetFrequency( Note::A_2 );
		double freqE = WellTemperament::GetFrequency( Note::E_3 );

		vector< double > seriseOfA;
		vector< double > seriseOfE;
		vector< vector< double > > chords;

		seriseOfA.push_back( freqA );
		seriseOfA.push_back( 3.0 * freqA );
		
		seriseOfE.push_back( freqE );
		seriseOfE.push_back( 2.0 * freqE );

		chords.push_back( seriseOfA );
		chords.push_back( seriseOfE );
		
		AudioRecorder32 recorder( 2, 1 );
		double time = 0.0;
		for ( int i = 0; i < chords.size(); i++ ) {
			const vector< double >& chord = chords[ i ];
			for ( int j = 0; j < chord.size(); j++ ) {
				const WaveTable& soundTable = WaveTableFactory::CreateSin( chord[ j ], 0.0, 0.5 );
				const SoundElement32* element;
				element = SoundElementFactory32::Create( soundTable, dynamicsTable, length );
				recorder.Record( 0, 0, time, element, 0.5, 0.5 );
			}
		}
		recorder.OutputAudioFile( folderPath + "experiment00.wav" );
	}
	
	if ( 1 == part ) {
	
		double time = 0.0;
		double length = 4.0;
	
		double swell = 0.0;
		double baseFreq = 440.0;
		double subFreq = 3.0 * baseFreq;
		double baseFreq2 = 0.0;
		double subFreq2 = 0.0;
		double phaseShift = 1.0 / 2.0;

		AudioRecorder32 recorder( 2, 1 );
			
		{	//	case 0, dynamics are the same, long swell
			swell = 1.0 / 3.0;
			baseFreq2 = baseFreq + swell;
			subFreq2 = subFreq + swell;

			std::vector< NoteInfo > noteInfos( 4 );
			noteInfos[ 0 ] = NoteInfo( baseFreq, length, 1.0 );
			noteInfos[ 1 ] = NoteInfo( subFreq, length, 1.0 );
			noteInfos[ 2 ] = NoteInfo( baseFreq2, length, 1.0, phaseShift );
			noteInfos[ 3 ] = NoteInfo( subFreq2, length, 1.0, phaseShift );

			std::vector< const SoundElement32* > chord;
			SoundGenerator::GenerateChordWithSineDynamicsTable( noteInfos, chord );
/*
			std::cout << chord[ 0 ]->ToString() << std::endl;
			std::cout << chord[ 1 ]->ToString() << std::endl;
			std::cout << chord[ 2 ]->ToString() << std::endl;
			std::cout << chord[ 3 ]->ToString() << std::endl;
*/
			recorder.Record( 0, 0, time, chord, 0.5, 0.5 );
			time += length;
		}

		{	//	case 1, dynamics are the same, short swell
			swell = 3.0;
			baseFreq2 = baseFreq + swell;
			subFreq2 = subFreq + swell;

			std::vector< NoteInfo > noteInfos( 4 );
			noteInfos[ 0 ] = NoteInfo( baseFreq, length, 1.0 );
			noteInfos[ 1 ] = NoteInfo( subFreq, length, 1.0 );
			noteInfos[ 2 ] = NoteInfo( baseFreq2, length, 1.0, phaseShift );
			noteInfos[ 3 ] = NoteInfo( subFreq2, length, 1.0, phaseShift );

			std::vector< const SoundElement32* > chord;
			SoundGenerator::GenerateChordWithSineDynamicsTable( noteInfos, chord );
			
			recorder.Record( 0, 0, time, chord, 0.5, 0.5 );
			time += length;
		}

		{	//	case 2, swell sound are smaller dynamics, long swell
			swell = 1.0 / 3.0;
			baseFreq2 = baseFreq + swell;
			subFreq2 = subFreq + swell;

			std::vector< NoteInfo > noteInfos( 4 );
			noteInfos[ 0 ] = NoteInfo( baseFreq, length, 1.0 );
			noteInfos[ 1 ] = NoteInfo( subFreq, length, 1.0 );
			noteInfos[ 2 ] = NoteInfo( baseFreq2, length, 0.5, phaseShift );
			noteInfos[ 3 ] = NoteInfo( subFreq2, length, 0.5, phaseShift );

			std::vector< const SoundElement32* > chord;
			SoundGenerator::GenerateChordWithSineDynamicsTable( noteInfos, chord );
			
			recorder.Record( 0, 0, time, chord, 0.5, 0.5 );
			time += length;
		}

		{	//	case 3, swell sound are smaller dynamics, long swell
			swell = 3.0;
			baseFreq2 = baseFreq + swell;
			subFreq2 = subFreq + swell;

			std::vector< NoteInfo > noteInfos( 4 );
			noteInfos[ 0 ] = NoteInfo( baseFreq, length, 1.0 );
			noteInfos[ 1 ] = NoteInfo( subFreq, length, 1.0 );
			noteInfos[ 2 ] = NoteInfo( baseFreq2, length, 0.5, phaseShift );
			noteInfos[ 3 ] = NoteInfo( subFreq2, length, 0.5, phaseShift );

			std::vector< const SoundElement32* > chord;
			SoundGenerator::GenerateChordWithSineDynamicsTable( noteInfos, chord );
			
			recorder.Record( 0, 0, time, chord, 0.5, 0.5 );
			time += length;
		}

		{	//	case 4, swell sound are larger dynamics, long swell
			swell = 1.0 / 3.0;
			baseFreq2 = baseFreq + swell;
			subFreq2 = subFreq + swell;

			std::vector< NoteInfo > noteInfos( 4 );
			noteInfos[ 0 ] = NoteInfo( baseFreq, length, 0.5 );
			noteInfos[ 1 ] = NoteInfo( subFreq, length, 0.5 );
			noteInfos[ 2 ] = NoteInfo( baseFreq2, length, 1.0, phaseShift );
			noteInfos[ 3 ] = NoteInfo( subFreq2, length, 1.0, phaseShift );
			std::vector< const SoundElement32* > chord;
			SoundGenerator::GenerateChordWithSineDynamicsTable( noteInfos, chord );
			
			recorder.Record( 0, 0, time, chord, 0.5, 0.5 );
			time += length;
		}

		{	//	case 5, swell sound are larger dynamics, long swell
			swell = 3.0;
			baseFreq2 = baseFreq + swell;
			subFreq2 = subFreq + swell;

			std::vector< NoteInfo > noteInfos( 4 );
			noteInfos[ 0 ] = NoteInfo( baseFreq, length, 0.5 );
			noteInfos[ 1 ] = NoteInfo( subFreq, length, 0.5 );
			noteInfos[ 2 ] = NoteInfo( baseFreq2, length, 1.0, phaseShift );
			noteInfos[ 3 ] = NoteInfo( subFreq2, length, 1.0, phaseShift );

			std::vector< const SoundElement32* > chord;
			SoundGenerator::GenerateChordWithSineDynamicsTable( noteInfos, chord );
			
			recorder.Record( 0, 0, time, chord, 0.5, 0.5 );
			time += length;
		}
		
		recorder.OutputAudioFile( folderPath + "experiment01.wav" );
	}
}
